package com.bob.debt.utils;

import java.io.StringReader;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

import org.w3c.dom.Node;
import org.xml.sax.InputSource;

public class XmlUtilChatGPT {

    /**
     * 将XML格式的字符串转换成Java实体类
     * @param xml XML格式的字符串
     * @param clazz Java实体类的Class对象
     * @return Java实体类对象
     */
    public static <T> T xmlToEntity(String xml, Class<T> clazz) {
        try {
            DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
            DocumentBuilder builder = factory.newDocumentBuilder();
            InputSource is = new InputSource(new StringReader(xml));
            Node node = builder.parse(is).getFirstChild();
            List<Field> fields = getAllFields(new ArrayList<Field>(), clazz);
            T obj = clazz.newInstance();

            for (Field field : fields) {
                field.setAccessible(true);
                if (node.getAttributes().getNamedItem(field.getName()) != null) {
                    String value = node.getAttributes().getNamedItem(field.getName()).getNodeValue();
                    setFieldValue(obj, field, value);
                }
            }
            return obj;
        } catch (Exception e) {
            throw new RuntimeException("XML转Java对象出错：" + e.getMessage(), e);
        }
    }

    /**
     * 将Java实体类对象转换成XML格式的字符串
     * @param obj Java实体类对象
     * @return XML格式的字符串
     */
    public static String entityToXml(Object obj) {
        StringBuilder sb = new StringBuilder();
        Class<? extends Object> clazz = obj.getClass();
        sb.append("<").append(clazz.getSimpleName()).append(" ");

        List<Field> fields = getAllFields(new ArrayList<Field>(), clazz);
        for (Field field : fields) {
            try {
                field.setAccessible(true);
                Object fieldValue = field.get(obj);
                if (fieldValue != null)
                    sb.append(field.getName()).append("=\"").append(fieldValue.toString()).append("\" ");
            } catch (Exception e) {
                throw new RuntimeException("Java对象转XML出错：" + e.getMessage(), e);
            }
        }
        sb.append("/>");
        return sb.toString();
    }

    /**
     * 递归获取Java实体类中的所有字段，包括父类的字段
     * @param fields 字段集合
     * @param clazz Java实体类的Class对象
     * @return 所有字段的集合
     */
    private static List<Field> getAllFields(List<Field> fields, Class<?> clazz) {
        fields.addAll(0, getDeclaredFields(clazz));
        if (clazz.getSuperclass() != null && !clazz.getSuperclass().equals(Object.class)) {
            getAllFields(fields, clazz.getSuperclass());
        }
        return fields;
    }

    /**
     * 获取Java实体类中声明的所有字段，不包括父类的字段
     * @param clazz Java实体类的Class对象
     * @return 字段的集合
     */
    private static List<Field> getDeclaredFields(Class<?> clazz) {
        List<Field> fields = new ArrayList<Field>();
        for (Field field : clazz.getDeclaredFields()) {
            fields.add(field);
        }
        return fields;
    }

    /**
     * 为Java实体类中的指定字段设置值
     * @param obj Java实体类对象
     * @param field 字段对象
     * @param value 字段需要设置的值
     * @throws Exception 设置值时可能会抛出异常
     */
    private static void setFieldValue(Object obj, Field field, String value) throws Exception {
        Class<?> type = field.getType();
        if (type.equals(int.class)) {
            field.set(obj, Integer.parseInt(value));
        } else if (type.equals(long.class)) {
            field.set(obj, Long.parseLong(value));
        } else if (type.equals(double.class)) {
            field.set(obj, Double.parseDouble(value));
        } else if (type.equals(float.class)) {
            field.set(obj, Float.parseFloat(value));
        } else if (type.equals(boolean.class)) {
            field.set(obj, Boolean.parseBoolean(value));
        } else {
            field.set(obj, value);
        }
    }


}

//        这个工具类提供了两个方法，一个是将XML格式的字符串转换成Java实体类的方法，另一个则是将Java实体类对象转换成XML格式的字符串的方法。
//
//        要使用该工具类，我们只需要调用其中的一个方法即可，例如：
//
//        ```java
//        String xml = "<User id=\"100\" name=\"Tom\" age=\"18\" sex=\"男\"/>";
//        User user = XmlUtil.xmlToEntity(xml, User.class);
//        System.out.println(user.getId());
//        System.out.println(user.getName());
//        System.out.println(user.getAge());
//        System.out.println(user.getSex());
//
//        User user2 = new User();
//        user2.setId(200);
//        user2.setName("Jerry");
//        user2.setAge(20);
//        user2.setSex("男");
//        String xml2 = XmlUtil.entityToXml(user2);
//        System.out.println(xml2);
//
//        以上代码将输出：
//
//        100
//        Tom
//        18
//        男
//<User id="200" name="Jerry" age="20" sex="男" />
//
//        这个工具类通过反射机制实现了XML格式的字符串与Java实体类的相互转换，可以方便快捷地使用XML格式来传递数据。 ♨
